package com.example;

import com.example.config.GameConfig;
import com.example.frame.TetrisFrame;
import com.example.model.TetrisNode;
import com.example.util.TreeUtil;

import javax.swing.*;
import java.io.*;
import java.util.*;

public class Main {
    public static ArrayList<Integer> iShapeIndexList = new ArrayList<>();
    static {
        int currentRandomNum = GameConfig.getSeed();
        for(int i=0;i<10000;i++){
            int shapeIndex = 0;
            currentRandomNum = GameConfig.getRandomNumber(currentRandomNum);
            int weightIndex = currentRandomNum % 29;
            if (weightIndex >= 0 && weightIndex <= 1) {
                shapeIndex = 0;
            } else if (weightIndex > 1 && weightIndex <= 4) {
                shapeIndex = 1;
            } else if (weightIndex > 4 && weightIndex <= 7) {
                shapeIndex = 2;
            } else if (weightIndex > 7 && weightIndex <= 11) {
                shapeIndex = 3;
            } else if (weightIndex > 11 && weightIndex <= 16) {
                shapeIndex = 4;
            } else if (weightIndex > 16 && weightIndex <= 22) {
                shapeIndex = 5;
            } else if (weightIndex > 22) {
                shapeIndex = 6;
            }
            if(shapeIndex ==0){
                iShapeIndexList.add(i);
            }
        }
    }

    public static void main(String[] args) throws Exception {



//        TetrisFrame frame = new TetrisFrame(DeserializeTetrisNode("D:/test/6.txt"));
//        JMenuBar menu = new JMenuBar();
//        frame.setJMenuBar(menu);
//        JMenu game = new JMenu("游戏");
//        JMenuItem newgame = game.add("新游戏");
//        JMenuItem pause = game.add("暂停");
//        JMenuItem goon = game.add("继续");
//        JMenuItem exit = game.add("退出");
//        JMenu help = new JMenu("帮助");
//        JMenuItem about = help.add("关于");
//        menu.add(game);
//        menu.add(help);
//        frame.setLocationRelativeTo(null);
//        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//        frame.setSize(220, 275);
//        frame.setTitle("TetrisSolution");
//        // frame.setUndecorated(true);
//        frame.setVisible(true);
//        frame.setResizable(false);



        //TreeUtil测试
//        TetrisNode tetrisNode = new TetrisNode();
//        List<TetrisNode> list= TreeUtil.getAllChildNode(tetrisNode);
//        for(int i=0;i<list.size();i++){
//        System.out.println("=============="+i);
//            list.get(i).showMap();
//        }

//        long startTime = System.currentTimeMillis();
//        //
        int currentIndex = 0;

        TetrisNode rootNode = DeserializeTetrisNode("D:/test/16.txt");//new TetrisNode();//
        for(int n = 0;n<iShapeIndexList.size();n++){
            if(rootNode.getBlockCount() <= iShapeIndexList.get(n)){
                currentIndex = n;
            }
        }
        System.out.println("currentIndex:"+currentIndex);
//
//        rootNode.showMap();
//        TetrisNode res = dfs(rootNode,rootNode.getBlockCount()+5);
//        res.showMap();
////        SerializeTetrisNode(res,"D:/test/"+res.getBlockCount()+".txt");
//        long endTime = System.currentTimeMillis();
//        System.out.println("time:"+(endTime - startTime));


        LinkedList<Integer> linkedList = new LinkedList<>();
//        //保存第一步文件
//        SerializeTetrisNode(rootNode,"D:/test/"+rootNode.getBlockCount()+".txt");
        linkedList.add(rootNode.getBlockCount());
        TetrisNode randomNode = (TetrisNode)rootNode.clone();
        Random random = new Random();
        long retryCount = 0;
        TetrisNode tempNode = (TetrisNode)rootNode.clone();
        while(randomNode.getBlockCount()<=10000){
            while(true){
                while(true){
//                    int randomWeight = 0;
                    int randomIndex = 0;
                    List<TetrisNode> list= TreeUtil.getAllChildNode(randomNode,(randomNode.getBlockType()==0 || randomNode.getBlockSum()>100 || rootNode.getBlockHeight()>=14||retryCount>100000));
                    if(list.size() == 0){
                        break;
                    }
                    randomIndex = (int)(Math.random()*100)%list.size();

//                    int weightSum = 0;
//                    for(int k=0;k<list.size();k++){
//                        weightSum += list.get(k).weight;
//                    }
//                    randomWeight = random.nextInt(weightSum);
//                    for(int k=0;k<list.size();k++){
//                        randomWeight-=list.get(k).weight;
//                        if(randomWeight<=0){
//                            randomIndex = k;
//                            break;
//                        }
//                    }
                    randomNode = list.get(randomIndex);
                    if(randomNode.getBlockCount() == iShapeIndexList.get(randomIndex)){
                        break;
                    }

                }
                boolean checkHole =  randomNode.checkHole();
                if( checkHole && randomNode.getScore()){
                    retryCount = 0;
                    //存档
                    SerializeTetrisNode(randomNode,"D:/test/"+randomNode.getBlockCount()+".txt");
                    tempNode = randomNode;
                    linkedList.add(randomNode.getBlockCount());
                    System.out.println("currentIndex:"+randomNode.getBlockCount());

                    break;
                }else{
                    retryCount++;
                    if(retryCount%10000==0){
                        if(retryCount >= 200000){
                            //执行回退操作
                            retryCount = 0;
                            //读档
                            if(linkedList.size()>=2){
                                linkedList.removeLast();
                            }
                            randomNode = DeserializeTetrisNode("D:/test/"+linkedList.getLast()+".txt");
                            System.out.println("rollbackIndex:"+randomNode.getBlockCount());

                        }
                        System.out.println("重试次数:"+retryCount+",sum:"+randomNode.getBlockSum()+",blockCount:"+randomNode.getBlockCount());
                    }

                    randomNode = tempNode;
                }
            }
        }
        randomNode.showMap();
        for(int k=0;k<randomNode.tetrisPaths.size();k++){
            if(randomNode.tetrisPaths.get(k).isFirstCount){
                System.out.println("//"+randomNode.tetrisPaths.get(k).blockCount);
            }
            System.out.println(randomNode.tetrisPaths.get(k).toString());
        }

        long endTime = System.currentTimeMillis();
        System.out.println("time:"+(endTime - startTime));


    }

    private static void SerializeTetrisNode(TetrisNode node,String fileName) throws FileNotFoundException,
            IOException {
        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
                new File(fileName)));
        oo.writeObject(node);
        System.out.println("TetrisNode serialize success");
        oo.close();
    }

    private static TetrisNode DeserializeTetrisNode(String fileName) throws Exception, IOException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                new File(fileName)));
        TetrisNode node = (TetrisNode) ois.readObject();
        System.out.println("TetrisNode deserialize success");
        return node;
    }
    //注意检索深度，避免内存爆炸
    public static TetrisNode dfs(TetrisNode node,int depth){
        int total = 0;
        if(depth - node.getBlockCount() >=20){
            System.out.println("检索深度超过最大值");
            return null;
        }
        if(depth <= node.getBlockCount()){
            System.out.println("检索深度小于当前节点深度");
            return null;
        }
        TetrisNode result = (TetrisNode)node.clone();
        TetrisNode temp = (TetrisNode)node.clone();
        int count=0;
        LinkedList<TetrisNode> list = new LinkedList<>();
        list.add(temp);

        while(!list.isEmpty()){
            TetrisNode tetrisNode = list.removeFirst();
            List<TetrisNode> tetrisNodes = TreeUtil.getAllChildNode(tetrisNode,(tetrisNode.getBlockType() == 0));
//            System.out.println("=============="+tetrisNodes.size());
            for(int i=0;i<tetrisNodes.size();i++){
                total++;
                if( tetrisNodes.get(i).getBlockCount()<depth){
                    list.add(tetrisNodes.get(i));
                }
                if( (tetrisNodes.get(i).getBlockCount()==depth) && tetrisNodes.get(i).checkHole()){
                    count++;
//                    int exScore1 = getExScore(tetrisNodes.get(i).getBlockHeight(),tetrisNodes.get(i).getScore(),tetrisNodes.get(i).getBlockSum());
//                    int exScore2 = getExScore(result.getBlockHeight(),result.getScore(),result.getBlockSum());
                    if(count ==1||result.getStdev() > tetrisNodes.get(i).getStdev()){//方差越小越好
                        result = (TetrisNode) tetrisNodes.get(i).clone();
                    }
                }
            }
        }
        System.out.println("检索完毕,共检测"+total+"个对象");
        System.out.println("检索深度范围:["+node.getBlockCount()+","+depth+"]");
        System.out.println("共找到"+count+"个结果符合条件");
        try {
            SerializeTetrisNode(result,"D:/test/"+result.getBlockCount()+".txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
    //返回期望分数，用于做决策,高度越低越好，分数越高越好
    public static int getExScore(int height,int score,int sum){
        return (-height*10+score+sum);
    }
}
